package common.meters;

public class RateMeter
{
    private long count;
    private float lastRate;
    private long last;
    private long lastCount;
    final private long samplingInterval;

    synchronized public RateMeter getSnapShot()
    {
        RateMeter meter=new RateMeter(this.samplingInterval);
        meter.count=count;
        meter.lastRate=lastRate;
        meter.last=last;
        meter.lastCount=lastCount;
        return meter;
    }
    public long getLastTick()
    {
        return last;
    }

    public long getCount()
    {
        return count;
    }

    public long getSamplingInterval()
    {
        return samplingInterval;
    }

    public RateMeter(long samplingInterval)
    {
        this.samplingInterval = samplingInterval;
        reset();
    }

    synchronized public void reset()
    {
        lastCount = count = 0;
        last = System.currentTimeMillis() - 2 * samplingInterval;
    }

    synchronized public void increment()
    {
        count++;
    }

    synchronized public void change(long amount)
    {
        count += amount;
    }

    public float getRate()
    {
        long nowCount = count;
        long now = System.currentTimeMillis();

        long duration = now - last;
        long deltaCount = nowCount - lastCount;
        float rate = duration > 0 ? (float) (deltaCount * 1000) / (float) duration : 0;
        if (duration > samplingInterval)
        {
            lastRate = rate;
        }
        else
        {
            float ratio = (float) duration / (float) samplingInterval;
            lastRate = rate * ratio + (1.0f - ratio) * lastRate;
        }
        lastCount = nowCount;
        last = now;
        return lastRate;
    }
}
